/********************************************************************************
* @file    bsp_adc.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2022-02-10
* @brief   NULL
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include "RTE_Components.h"
#include CMSIS_device_header
#include "at32f4xx.h"
#include "at32f4xx_adc.h"

#include "bsp_gpio.h"
#include "bsp_exti.h"
#include "bsp_adc.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
#define ADC0_CH_NUM                   18

#define ADC0_CH0                      0
#define ADC0_CH1                      1
#define ADC0_CH2                      2
#define ADC0_CH3                      3
#define ADC0_CH4                      4
#define ADC0_CH5                      5
#define ADC0_CH6                      6
#define ADC0_CH7                      7
#define ADC0_CH8                      8
#define ADC0_CH9                      9
#define ADC0_CH10                     10
#define ADC0_CH11                     11
#define ADC0_CH12                     12
#define ADC0_CH13                     13
#define ADC0_CH14                     14
#define ADC0_CH15                     15
#define ADC0_CH16                     16
#define ADC0_CH17                     17

#define CH_NUM  (BS_ADC0_CH0 + BS_ADC0_CH1 + BS_ADC0_CH2 + BS_ADC0_CH3 + BS_ADC0_CH4 + BS_ADC0_CH5 + BS_ADC0_CH6 + BS_ADC0_CH7 + BS_ADC0_CH8 + BS_ADC0_CH9 + BS_ADC0_CH10 + BS_ADC0_CH11 + BS_ADC0_CH12 + BS_ADC0_CH13 + BS_ADC0_CH14 + BS_ADC0_CH15 + BS_ADC0_CH16 + BS_ADC0_CH17)
/* Private Variables ---------------------------------------------------------*/
// ADC初始化状态(0--deinit 1--init)
static bool g_adc_init = false;
// ADC采集数据存储buff
uint16_t bsp_adc0_val[ADC0_CH_NUM] = {0};
uint16_t bsp_adc0_temp_val[CH_NUM] = {0};

// 定义ADC采集完毕回调函数
typedef void(*bsp_adc0_callback)(void);
static bsp_adc0_callback irq_callback;
static uint8_t adc0_sample_tick = 0;
/****************结构体定义****************/
#if BS_ADC0_EN
ADC_InitType adc0_handle_t =
{
    .ADC_Mode              = ADC_Mode_Independent,
    .ADC_ScanMode          = ENABLE,                        // DISABLE 单通道  ENABLE 双通道
    .ADC_ContinuousMode    = DISABLE,                       // DISABLE 单次    ENABLE 连续
    .ADC_ExternalTrig      = ADC_ExternalTrig_None,
    .ADC_DataAlign         = ADC_DataAlign_Right,
    .ADC_NumOfChannel      = CH_NUM
};
#endif
/* External Variables --------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
#if BS_ADC0_EN
/**
 * @brief  将ADC采集的值重新排序到另一个数组
 */
static void bsp_adc0_val_copy(void)
{
    uint8_t num = 0;
    bool flag = false;

    for (uint8_t i = 0; i < ADC0_CH_NUM; i++)
    {
        if (i == ADC0_CH0 && BS_ADC0_CH0)
        {
            flag = true;
        }
        else if(i == ADC0_CH1 && BS_ADC0_CH1)
        {
            flag = true;
        }
        else if(i == ADC0_CH2 && BS_ADC0_CH2)
        {
            flag = true;
        }
        else if(i == ADC0_CH3 && BS_ADC0_CH3)
        {
            flag = true;
        }
        else if(i == ADC0_CH4 && BS_ADC0_CH4)
        {
            flag = true;
        }
        else if(i == ADC0_CH5 && BS_ADC0_CH5)
        {
            flag = true;
        }
        else if(i == ADC0_CH6 && BS_ADC0_CH6)
        {
            flag = true;
        }
        else if(i == ADC0_CH7 && BS_ADC0_CH7)
        {
            flag = true;
        }
        else if(i == ADC0_CH8 && BS_ADC0_CH8)
        {
            flag = true;
        }
        else if(i == ADC0_CH9 && BS_ADC0_CH9)
        {
            flag = true;
        }
        else if(i == ADC0_CH10 && BS_ADC0_CH10)
        {
            flag = true;
        }
        else if(i == ADC0_CH11 && BS_ADC0_CH11)
        {
            flag = true;
        }
        else if(i == ADC0_CH12 && BS_ADC0_CH12)
        {
            flag = true;
        }
        else if(i == ADC0_CH13 && BS_ADC0_CH13)
        {
            flag = true;
        }
        else if(i == ADC0_CH14 && BS_ADC0_CH14)
        {
            flag = true;
        }
        else if(i == ADC0_CH15 && BS_ADC0_CH15)
        {
            flag = true;
        }
        else if(i == ADC0_CH16 && BS_ADC0_CH16)
        {
            flag = true;
        }
        else if(i == ADC0_CH17 && BS_ADC0_CH17)
        {
            flag = true;
        }
        if (flag)
        {
            flag = false;
            bsp_adc0_val[i] = bsp_adc0_temp_val[num];
            num++;
            if (num == CH_NUM)
            {
                break;
            }
        }
    }
}


/**
 * @brief  ADC0初始化，并使能通道
 */
void bsp_adc0_init(void)
{
    uint8_t ch = 0;
#if CH_NUM
    if (g_adc_init)
    {
        return;
    }
    /* ADCCLK = PCLK2/4 */
    RCC_ADCCLKConfig(RCC_APB2CLK_Div4);
    /* Enable ADC1 clocks */
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_ADC1, ENABLE);
    /* ADC1 configuration */
    ADC_Init(ADC1, &adc0_handle_t);
    // 使能通道
#if BS_ADC0_CH0
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH1
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH2
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH3
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH4
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH5
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_5, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH6
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_6, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH7
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_7, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH8
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH9
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_9, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH10
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH11
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH12
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_12, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH13
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_13, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH14
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH15
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_15, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH16
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, ch, ADC_SampleTime_28_5);
#endif
#if BS_ADC0_CH17
    ch++;
    ADC_RegularChannelConfig(ADC1, ADC_Channel_17, ch, ADC_SampleTime_28_5);
#endif
    /* Regular discontinuous mode channel number configuration */
    ADC_DiscModeChannelCountConfig(ADC1, 1);
    /* Enable regular discontinuous mode */
    ADC_DiscModeCtrl(ADC1, ENABLE);

    /* Enables Temperature Sensor and Vrefint Channel */
    ADC_TempSensorVrefintCtrl(ENABLE);
    ADC_INTConfig(ADC1, ADC_INT_EC, ENABLE);

    /* Enable ADC1 */
    ADC_Ctrl(ADC1, ENABLE);

    /* Enable ADC1 reset calibration register */
    ADC_RstCalibration(ADC1);
    /* Check the end of ADC1 reset calibration register */
    while(ADC_GetResetCalibrationStatus(ADC1));

    /* Start ADC1 calibration */
    ADC_StartCalibration(ADC1);
    /* Check the end of ADC1 calibration */
    while(ADC_GetCalibrationStatus(ADC1));

    NVIC_InitType NVIC_InitStructure;
    /* Configure and enable ADC interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                      = ADC1_2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    g_adc_init = true;
#endif
}

/**
 * @brief  ADC0功能关闭，并移除
 */
void bsp_adc0_deinit(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    ADC_Reset(ADC1);
    g_adc_init = false;
#endif
}

/**
 * @brief  ADC0 启动采样功能
 */
void bsp_adc0_start(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    /* Enable ADC1 */
    ADC_Ctrl(ADC1, ENABLE);
    /* Start ADC1 Software Conversion */
    ADC_SoftwareStartConvCtrl(ADC1, ENABLE); // 启动ADC中断转换
    adc0_sample_tick = 0;
#endif
}

/**
 * @brief  ADC0 停止采样功能
 */
void bsp_adc0_stop(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    /* Stop ADC1 Software Conversion */
    ADC_SoftwareStartConvCtrl(ADC1, DISABLE); // 停止ADC中断转换
    /* Stop ADC1 */
    ADC_Ctrl(ADC1, DISABLE);
#endif
}

#else
void bsp_adc0_init(void)
{
}

void bsp_adc0_deinit(void)
{
}

void bsp_adc0_start(void)
{
}
void bsp_adc0_stop(void)
{
}
#endif

/**
  * @brief  This function handles ADC1 and ADC2 global interrupts requests.
  */
#define CTRL2_EXTTRIG_SWSTR_Set     ((uint32_t)0x00500000)
void ADC1_2_IRQHandler(void)
{
#if BS_ADC0_EN
    if (ADC_GetINTStatus(ADC1, ADC_INT_EC))
    {
        bsp_adc0_temp_val[adc0_sample_tick] = (uint16_t) ADC1->RDOR;
        adc0_sample_tick ++;
        if (adc0_sample_tick > CH_NUM - 1)
        {
            adc0_sample_tick = 0;
            bsp_adc0_stop();
            bsp_adc0_val_copy();
            if (irq_callback)
            {
                irq_callback();
            }
        }
        else
        {
            ADC1->CTRL2 |= CTRL2_EXTTRIG_SWSTR_Set;
        }
        /* Clear ADC1 EC pending interrupt bit */
        ADC_ClearINTPendingBit(ADC1, ADC_INT_EC);
    }
#endif
}

/**
 * @brief  得到ADC0采样值
 * @param  ch_num: 通道值
 * @retval 通道对应的ADC值
 */
uint16_t bsp_adc0_get_ch_val(uint8_t ch_num)
{
    if (ch_num >= ADC0_CH_NUM)
    {
        return 0xFFFF;
    }
    return bsp_adc0_val[ch_num];
}

/**
 * @brief  注册ADC0采样完毕回调函数
 * @param  *event: 绑定回调事件
 * @retval 0--失败 1--成功
 */
bool bsp_adc0_irq_callback(void *event)
{
    if (irq_callback != NULL)
    {
        return false;
    }
    else
    {
        irq_callback = (bsp_adc0_callback)event;
    }
    return true;
}
